package com.basker.pisces.core;

import com.alibaba.fastjson.annotation.JSONField;
import com.basker.pisces.core.enums.DataObjectState;
import com.basker.pisces.core.exception.ReadOnlyObjectModifyException;
import com.basker.pisces.core.meta.IField;

/**
 * 数据对象接口，提供了读写字段、读写各类状态的方法
 *
 * @author hangwen
 */
public interface IDataContract extends IInitialize {

    /**
     * 清空已记录的旧值
     */
    void clearOldValues();

    /**
     * 获取对象指定字段的值
     *
     * @param field
     * @return
     */
    Object getFieldValue(IField field);

    /**
     * 获取字段的旧值，若没有更改过则返回null
     *
     * @return
     */
    Object getOldValue(String name);

    /**
     * 获取对象的主键值
     *
     * @return
     */
    @JSONField(serialize = false)
    Object getPkValue();

    /**
     * 获取对象的数据状态
     *
     * @return
     * @see DataObjectState
     */
    @JSONField(serialize = false)
    DataObjectState getState();

    /**
     * 对象的指定字段相对于持久层是否有更改
     *
     * @param fieldName
     * @return
     */
    boolean isChanged(String fieldName);

    /**
     * 对象是否从数据库加载而来
     *
     * @return
     */
    @JSONField(serialize = false)
    boolean isFromDB();

    /**
     * 对象的部分属性是否从数据表加载而来
     *
     * @param tableName
     * @return
     */
    boolean isFromDB(String tableName);

    /**
     * 对象是否只读，对于只读对象尝试设置字段值得话，会抛出{@link ReadOnlyObjectModifyException}
     *
     * @return
     */
    @JSONField(serialize = false)
    boolean isReadOnly();

    /**
     * 记录对象指定字段的旧值
     *
     * @param fieldName
     * @param oldValue
     */
    void recordOldValue(String fieldName, Object oldValue);

    /**
     * 设置对象指定字段的值
     *
     * @param field
     * @param value
     */
    void setFieldValue(IField field, Object value);

    /**
     * 设置对象是否从数据库加载而来
     *
     * @param fromDB
     */
    void setFromDB(boolean fromDB);

    /**
     * 设置对象的一部分属性，是否从指定的数据表加载而来
     *
     * @param tableName
     * @param fromDB
     */
    void setFromDB(String tableName, boolean fromDB);

    /**
     * 设置对象是否只读
     *
     * @param readOnly
     */
    void setReadOnly(boolean readOnly);

    /**
     * 设置对象的数据状态
     *
     * @param state
     */
    void setState(DataObjectState state);

}
